#include <stdio.h>
#include "BSP/SRAM/bsp_sram.h"

/**
  * @brief  Write n bytes continuously starting from specified address (WriteAddr + Bank1_SRAM3_ADDR)
  * @note   Byte-wise write operation
  * @param  pBuffer: Pointer to data buffer
  * @param  WriteAddr: Write address offset
  * @param  n: Number of bytes to write
  * @retval None
  */
void FSMC_SRAM_WriteBuffer(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t n)
{
  for(; n != 0; n--)
  {
    *(volatile uint8_t *)(Bank1_SRAM3_ADDR + WriteAddr) = *pBuffer;
    WriteAddr++;
    pBuffer++;
  }
}

/**
  * @brief  Read n bytes continuously starting from specified address (ReadAddr + Bank1_SRAM3_ADDR)
  * @note   Byte-wise read operation
  * @param  pBuffer: Pointer to data buffer
  * @param  ReadAddr: Read address offset
  * @param  n: Number of bytes to read
  * @retval None
  */
void FSMC_SRAM_ReadBuffer(uint8_t *pBuffer, uint32_t ReadAddr, uint32_t n)
{
  for(; n != 0; n--)
  {
    *pBuffer++ = *(volatile uint8_t *)(Bank1_SRAM3_ADDR + ReadAddr);
    ReadAddr++;
  }
}

/**
  * @brief  8-bit data read/write test
  * @note   Tests the entire SRAM with 8-bit data pattern
  * @param  None
  * @retval 0: Success, -1: Failure
  */
int rw_8bit_test(void)
{
  uint32_t i = 0;
  uint8_t ubWritedata_8b = 0, ubReaddata_8b = 0;  
  /* Write data to entire SRAM (8-bit mode) */
  for (i = 0; i < IS62WV51216_SIZE; i++)
  {
    *(volatile uint8_t*) (Bank1_SRAM3_ADDR + i) = (uint8_t)(ubWritedata_8b + i);
  }

  /* Read SRAM data and verify */
  for(i = 0; i < IS62WV51216_SIZE; i++ )
  {
    ubReaddata_8b = *(volatile uint8_t*)(Bank1_SRAM3_ADDR + i);  // Read data from address

    if(ubReaddata_8b != (uint8_t)(ubWritedata_8b + i))      // Verify data, return error if mismatch
    {
      printf("The 8-bit data read/write error!!!\r\n");
      return -1;
    }
  }
	printf("The 8-bit data read/write test succeeds!!!\r\n");
	return 0;
}

/**
  * @brief  16-bit data read/write test
  * @note   Tests the entire SRAM with 16-bit data pattern
  * @param  None
  * @retval 0: Success, -1: Failure
  */
int rw_16bit_test(void)
{
  uint32_t i = 0;
  uint16_t ubWritedata_16b = 0, ubReaddata_16b = 0;  
  /* Write data to entire SRAM (16-bit mode) */
  for (i = 0; i < IS62WV51216_SIZE/2; i++)
  {
    *(volatile uint16_t*) (Bank1_SRAM3_ADDR + i*2) = (uint16_t)(ubWritedata_16b + i);
  }

  /* Read SRAM data and verify */
  for(i = 0; i < IS62WV51216_SIZE/2; i++ )
  {
    ubReaddata_16b = *(volatile uint16_t*)(Bank1_SRAM3_ADDR + i*2);  // Read data from address

    if(ubReaddata_16b != (uint16_t)(ubWritedata_16b + i))      // Verify data, return error if mismatch
    {
      printf("The 16-bit data read/write error!!!\r\n");
      return -1;
    }
  }
	printf("The 16-bit data read/write test succeeds!!!\r\n");
	return 0;
}

/**
  * @brief  Continuous byte-wise write and read test
  * @note   Tests buffer write/read functionality
  * @param  None
  * @retval None
  */
void rw_nByte_test(void)
{
  uint32_t i = 0;
  uint8_t temp[32] = "This is my sram test!!!";
  uint8_t read[32] = {0};

  FSMC_SRAM_WriteBuffer(temp, 0, sizeof(temp));
  for(i = 0; i < 32; i++)
  {
    if(i % 2 == 0)
    {
      printf("\r\n0x%p:", (uint8_t*)(Bank1_SRAM3_ADDR + i));
    }
    printf("%c ", *(volatile uint8_t*)(Bank1_SRAM3_ADDR + i)); // Display test data
  }
  printf("\r\n\r\n");

  FSMC_SRAM_ReadBuffer(read, 0, sizeof(read));
  printf("read data:%s\r\n", read);
}

#if PrestoredTest == 1
#define MDK_PRG
#ifdef MDK_PRG
uint8_t testSram[500] __attribute__((at(0X68000000)));// Test array for MDK
#endif
#ifdef MAKEFILE_PRG
uint8_t testSram[500] __attribute__((section(".sram")));// Test array for Makefile
#endif
/**
  * @brief  SRAM test with pre-stored data
  * @note   Tests SRAM functionality with predefined test pattern
  * @param  None
  * @retval None
  */
void SRAM_Test(void)
{
  uint32_t i = 0;

  for(i = 0; i < 10; i++)
  {
    testSram[i] = 2 * i + 1; // Pre-store test data
    printf("%p testSram[%d]:%d\r\n", &testSram[i], i, testSram[i]); // Display test data
  }
  printf("\r\n\r\n");

  for(i = 0; i < 10; i++)
  {
    if(i % 2 == 0)
    {
      printf("\r\n%p:", (uint8_t*)(Bank1_SRAM3_ADDR + i));
    }
    printf("%d ", *(volatile uint8_t*)(Bank1_SRAM3_ADDR + i)); // Display test data
  }
  printf("\r\n\r\n");
}
#endif
